#include <linux/utsname.h>
#include <linux/device.h>

struct f_dummy { struct usb_function function; };

static inline struct f_dummy *func_to_dum(struct usb_function *f) { return container_of(f, struct f_dummy, function); }

static struct usb_interface_descriptor dummy_intf = {
	.bLength =		sizeof dummy_intf,
	.bDescriptorType =	USB_DT_INTERFACE,
	.bNumEndpoints =	0,
	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
};

static struct usb_descriptor_header *fs_dummy_descs[] = { (struct usb_descriptor_header *) &dummy_intf, NULL };

static struct usb_string strings_dummy[] = { [0].s = "dummy", {} };

static struct usb_gadget_strings stringtab_dum = {
	.language	= 0x0409,
	.strings	= strings_dummy,
};

static struct usb_gadget_strings *dummy_strings[] = { &stringtab_dum, NULL };

static int __init dummy_bind(struct usb_configuration *c, struct usb_function *f)
{
	int id;
	id = usb_interface_id(c, f);
	if (id < 0)
		return id;
	dummy_intf.bInterfaceNumber = id;
	return 0;
}

static void dummy_unbind(struct usb_configuration *c, struct usb_function *f) { kfree(func_to_dum(f)); }

static int dummy_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { return 0; }

static void dummy_disable(struct usb_function *f) { }

static int __init dummy_bind_config(struct usb_configuration *c)
{
	struct f_dummy	*dum;
	int			status;

	dum = kzalloc(sizeof *dum, GFP_KERNEL);
	if (!dum)
		return -ENOMEM;

	dum->function.name = "dummy";
	dum->function.descriptors = fs_dummy_descs;
	dum->function.bind = dummy_bind;
	dum->function.unbind = dummy_unbind;
	dum->function.set_alt = dummy_set_alt;
	dum->function.disable = dummy_disable;

	status = usb_add_function(c, &dum->function);
	if (status)
		kfree(dum);
	return status;
}

static struct usb_configuration dummy_driver = {
	.label		= "dummy",
	.strings	= dummy_strings,
	.bind		= dummy_bind_config,
	.bConfigurationValue = 2,
	.bmAttributes	= USB_CONFIG_ATT_SELFPOWER,
};

int __init dummy_add(struct usb_composite_dev *cdev)
{
	int id;

	id = usb_string_id(cdev);
	if (id < 0)
		return id;
	strings_dummy[0].id = id;

	dummy_intf.iInterface = id;
	dummy_driver.iConfiguration = id;

	return usb_add_config(cdev, &dummy_driver);
}
